#include  "company.h"
#include  "illegalArguments.h"

class Remover
{
    public:
            Remover( int _id): id( _id) { }
            int getID( ) const
            {
                return id;
            }
            void setID( int _id)
            {
                id = _id;
            }
    private:
            int id;
};

class RemoveByID: public Remover
{
    public:
            RemoveByID( int _id) : Remover(_id) { }
            virtual bool operator( )( const Employee* employee)
            {
                if ( employee->getID( ) == this->getID( ))
                {
                    delete employee;
                    return true;
                }
                return false;
            }
};

class RemoveAll: public Remover
{
    public:
            RemoveAll( ): Remover( -1) { }
            virtual bool operator( )( const Employee* employee)
            {
                delete employee;
                return true;
            }
};

Company::Company( )
{
    db.clear( );
}

void Company::add( const Employee* employee)
{
    if ( NULL == employee)
    {
        IllegalArguments excpt;
        excpt.raise( );
    }
    if ( contains( employee->getID()))
        return;
    Employee* tmp = employee->clone( );
    db.push_back( tmp);
}

Company& Company::operator+=( const Employee* employee)
{
    this->add( employee);
    return *this;
}

void Company::remove( int id)
{
    RemoveByID remover( id);
    db.remove_if( remover);
}

Company& Company::operator-=( int id)
{
    this->remove( id);
    return *this;
}

bool Company::contains( int id)
{
    for ( std::list< Employee*>::iterator it = db.begin( );
            it != db.end( ); 
            ++it)
        if ( ( ( *it)->getID( )) == id)
            return true;
    return false;
}

bool Company::contains( const Employee* employee)
{
    return this->contains( employee->getID( ));
}

Employee* Company::find( int id) 
{
    for ( std::list< Employee*>::iterator it = db.begin( );
            it != db.end( ); 
            ++it)
        if ( ( ( *it)->getID( )) == id)
            return (*it)->clone( );
    return NULL;
}

std::ostream& Company::print( std::ostream& os) const
{
    if ( db.size( ) == 0 )
    {
        return os << "Company is empty" << std::endl;
    }
    os << "Company employees:" << std::endl;
    for ( std::list< Employee*>::const_iterator it = db.begin( );
            it != db.end( ); 
            ++it)
    {
            os << " " << *((Employee*)(*it)) ;
    }
    return os;
}

std::ostream& operator<<( std::ostream& os, const Company& company)
{
    return company.print( os);
}

Employee* Company::operator[]( int id)
{
    return this->find( id);
}

Company::~Company( )
{
    RemoveAll remover;
    db.remove_if( remover);
}
